// controllers/menu_controller.go
package controllers

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"go-admin-system/models"
)

type MenuController struct {
	db *gorm.DB
}

func NewMenuController(db *gorm.DB) *MenuController {
	return &MenuController{db}
}

// GetMenus 获取所有菜单
func (mc *MenuController) GetMenus(c *gin.Context) {
	var menus []models.Menu
	if err := mc.db.Order("sort asc").Find(&menus).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取菜单列表失败"})
		return
	}

	// 构建菜单树
	menuTree := buildMenuTree(menus, 0)

	c.JSON(http.StatusOK, gin.H{"menus": menuTree})
}

// buildMenuTree 构建菜单树
func buildMenuTree(menus []models.Menu, parentID uint) []models.Menu {
	var tree []models.Menu

	for _, menu := range menus {
		if menu.ParentID == parentID {
			children := buildMenuTree(menus, menu.ID)
			if len(children) > 0 {
				menu.Children = children
			}
			tree = append(tree, menu)
		}
	}

	return tree
}

// GetMenu 获取单个菜单
func (mc *MenuController) GetMenu(c *gin.Context) {
	var menu models.Menu
	if err := mc.db.First(&menu, c.Param("id")).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "菜单不存在"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"menu": menu})
}

// CreateMenu 创建菜单
func (mc *MenuController) CreateMenu(c *gin.Context) {
	var input struct {
		Name     string `json:"name" binding:"required"`
		Path     string `json:"path"`
		ParentID uint   `json:"parent_id"`
		Sort     int    `json:"sort"`
		Icon     string `json:"icon"`
		Status   int    `json:"status"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	menu := models.Menu{
		Name:     input.Name,
		Path:     input.Path,
		ParentID: input.ParentID,
		Sort:     input.Sort,
		Icon:     input.Icon,
		Status:   input.Status,
	}

	if err := mc.db.Create(&menu).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建菜单失败"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"menu": menu})
}

// UpdateMenu 更新菜单
func (mc *MenuController) UpdateMenu(c *gin.Context) {
	var menu models.Menu
	if err := mc.db.First(&menu, c.Param("id")).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "菜单不存在"})
		return
	}

	var input struct {
		Name     string `json:"name"`
		Path     string `json:"path"`
		ParentID uint   `json:"parent_id"`
		Sort     int    `json:"sort"`
		Icon     string `json:"icon"`
		Status   int    `json:"status"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if input.Name != "" {
		menu.Name = input.Name
	}

	if input.Path != "" {
		menu.Path = input.Path
	}

	menu.ParentID = input.ParentID
	menu.Sort = input.Sort

	if input.Icon != "" {
		menu.Icon = input.Icon
	}

	menu.Status = input.Status

	if err := mc.db.Save(&menu).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新菜单失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"menu": menu})
}

// DeleteMenu 删除菜单
func (mc *MenuController) DeleteMenu(c *gin.Context) {
	var menu models.Menu
	if err := mc.db.First(&menu, c.Param("id")).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "菜单不存在"})
		return
	}

	// 检查是否有子菜单
	var count int64
	mc.db.Model(&models.Menu{}).Where("parent_id = ?", menu.ID).Count(&count)

	if count > 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请先删除子菜单"})
		return
	}

	// 先删除关联表数据
	mc.db.Where("menu_id = ?", menu.ID).Delete(&models.RoleMenu{})

	if err := mc.db.Delete(&menu).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除菜单失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "菜单删除成功"})
}

// AssignRoles 分配角色访问菜单
func (mc *MenuController) AssignRoles(c *gin.Context) {
	var menu models.Menu
	if err := mc.db.First(&menu, c.Param("id")).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "菜单不存在"})
		return
	}

	var input struct {
		RoleIDs []uint `json:"role_ids" binding:"required"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 先删除菜单现有的角色关联
	mc.db.Where("menu_id = ?", menu.ID).Delete(&models.RoleMenu{})

	// 添加新的角色关联
	for _, roleID := range input.RoleIDs {
		roleMenu := models.RoleMenu{
			RoleID: roleID,
			MenuID: menu.ID,
		}

		if err := mc.db.Create(&roleMenu).Error; err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "分配角色失败"})
			return
		}
	}

	c.JSON(http.StatusOK, gin.H{"message": "菜单角色分配成功"})
}
